package com.ly.mp.busicen.common.context;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/**
 * 动态转换
 * @author ly-liuweisong
 *
 */
public class BusicenConvert {

    /***
     * List Convert
     * @param <T>
     * @param clazz
     * @param list
     * @return
     */
    public static <T> List<T> convertList(Class<T> clazz, List<?> list) {
        if (list == null) {
            return null;
        }
        List<T> result = new ArrayList<T>();
        result = list.stream().map(m -> convert(clazz, m)).collect(Collectors.toList());
        return result;
    }

    /**
     * List Parallel Convert
     * @param <T>
     * @param clazz
     * @param list
     * @return
     */
    public static <T> List<T> convertParallelList(Class<T> clazz, List<?> list) {
        if (list == null) {
            return null;
        }
        List<T> result = new ArrayList<T>();
        result = list.parallelStream().map(m -> convert(clazz, m)).collect(Collectors.toList());
        return result;
    }

    /**
     * Convert Using CGLIB
     * @param <T>
     * @param clazz
     * @param entity
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T convert(Class<T> clazz, Object entity) {
        if (entity == null) {
            return null;
        }
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object obj, Method method, Object[] param, MethodProxy px) throws Throwable {
                Object result = method.invoke(entity, param);
                return result;
            }
        });

        return (T) enhancer.create();
    }

    /**
     * Convert Using DynamicProxy
     * @param <T>
     * @param clazz
     * @param entity
     * @return
     */
    
    @SuppressWarnings("unchecked")
    public static <T> T convert2(Class<T> clazz, Object entity) {
        if (entity == null) {
            return null;
        }
        ClassLoader classLoader = clazz.getClassLoader();
        Class<?>[] interfaces = new Class<?>[] { clazz };
        return (T) Proxy.newProxyInstance(classLoader, interfaces, (proxy, method, args) -> {
            return method.invoke(entity, args);
        });
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("a", "b");
        TestMap test = convert2(TestMap.class, map);
        Object oo = test.get("a");
        System.out.println(oo.toString());

    }

    public static interface TestMap extends Map<String, Object> {

    }
}
